using AutoMapper;
using MediatR;
using RBAC.Domain.SmartHealthcare.Hosiptial;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using SmartHealthcare.Read.Api.Application.Command.HospitalExpense;
using SmartHealthcare.Read.Api.DTo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace SmartHealthcare.Read.Api.Application.Handler.HospitalExpense
{
    /// <summary>
    /// 获取住院费用统计处理器
    /// </summary>
    public class GetExpenseStatisticsHandler : IRequestHandler<GetExpenseStatisticsCommand, APIResult<ExpenseStatisticsDto>>
    {
        private readonly IBaseRepository<HospitalExpenseModel> expenseRepository;
        private readonly IBaseRepository<PatientListModel> patientRepository;
        private readonly IBaseRepository<InpatientRegistryModel> registryRepository;
        private readonly IMapper mapper;
        private readonly ILogger<GetExpenseStatisticsHandler> logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="expenseRepository">住院费用记录仓储</param>
        /// <param name="patientRepository">患者信息仓储</param>
        /// <param name="registryRepository">住院登记仓储</param>
        /// <param name="mapper">对象映射器</param>
        /// <param name="logger">日志记录器</param>
        public GetExpenseStatisticsHandler(
            IBaseRepository<HospitalExpenseModel> expenseRepository,
            IBaseRepository<PatientListModel> patientRepository,
            IBaseRepository<InpatientRegistryModel> registryRepository,
            IMapper mapper,
            ILogger<GetExpenseStatisticsHandler> logger)
        {
            this.expenseRepository = expenseRepository;
            this.patientRepository = patientRepository;
            this.registryRepository = registryRepository;
            this.mapper = mapper;
            this.logger = logger;
        }

        /// <summary>
        /// 处理获取住院费用统计请求
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>费用统计信息</returns>
        public Task<APIResult<ExpenseStatisticsDto>> Handle(GetExpenseStatisticsCommand request, CancellationToken cancellationToken)
        {
            APIResult<ExpenseStatisticsDto> result = new APIResult<ExpenseStatisticsDto>();

            try
            {
                logger.LogInformation($"开始获取住院费用统计，病人卡号：{request.MedicalCard}，住院登记ID：{request.InpatientRegistryId}");

                // 参数验证
                if (string.IsNullOrWhiteSpace(request.MedicalCard) && !request.InpatientRegistryId.HasValue)
                {
                    result.Code = APIEnums.Fail;
                    result.Msg = "病人卡号和住院登记ID不能同时为空";
                    return Task.FromResult(result);
                }

                // 构建查询条件
                var query = expenseRepository.GetALL().Where(e => e.IsDeleted == false);

                if (!string.IsNullOrWhiteSpace(request.MedicalCard))
                {
                    query = query.Where(e => e.MedicalCard == request.MedicalCard);
                }

                if (request.InpatientRegistryId.HasValue)
                {
                    query = query.Where(e => e.InpatientRegistryId == request.InpatientRegistryId.Value);
                }

                if (request.StartTime.HasValue)
                {
                    query = query.Where(e => e.ExpenseTime >= request.StartTime.Value);
                }

                if (request.EndTime.HasValue)
                {
                    query = query.Where(e => e.ExpenseTime <= request.EndTime.Value);
                }

                // 获取费用记录
                var expenses = query.ToList();

                if (expenses.Count == 0)
                {
                    result.Code = APIEnums.Success;
                    result.Msg = "未找到符合条件的费用记录";
                    result.Data = new ExpenseStatisticsDto();
                    return Task.FromResult(result);
                }

                // 创建统计结果
                var statistics = new ExpenseStatisticsDto
                {
                    MedicalCard = expenses.First().MedicalCard,
                    PatientName = expenses.First().PatientName,
                    InpatientRegistryId = expenses.First().InpatientRegistryId,
                    DepartmentName = expenses.First().DepartmentName,
                    TotalAmount = expenses.Sum(e => e.TotalAmount),
                    TotalInsuranceAmount = expenses.Sum(e => e.InsuranceAmount),
                    TotalSelfPayAmount = expenses.Sum(e => e.SelfPayAmount)
                };

                // 按类型统计
                if (request.GroupByType)
                {
                    var groupByType = expenses
                        .GroupBy(e => e.ItemType)
                        .Select(g => new ExpenseTypeStatisticsDto
                        {
                            ItemType = g.Key,
                            TotalAmount = g.Sum(e => e.TotalAmount),
                            InsuranceAmount = g.Sum(e => e.InsuranceAmount),
                            SelfPayAmount = g.Sum(e => e.SelfPayAmount),
                            ItemCount = g.Count()
                        })
                        .OrderByDescending(g => g.TotalAmount)
                        .ToList();

                    statistics.TypeStatistics = groupByType;
                }

                // 按天统计
                if (request.GroupByDay)
                {
                    var groupByDay = expenses
                        .GroupBy(e => e.ExpenseTime.Date)
                        .Select(g => new DailyExpenseStatisticsDto
                        {
                            Date = g.Key,
                            TotalAmount = g.Sum(e => e.TotalAmount),
                            InsuranceAmount = g.Sum(e => e.InsuranceAmount),
                            SelfPayAmount = g.Sum(e => e.SelfPayAmount),
                            TypeStatistics = g.GroupBy(e => e.ItemType)
                                .Select(tg => new ExpenseTypeStatisticsDto
                                {
                                    ItemType = tg.Key,
                                    TotalAmount = tg.Sum(e => e.TotalAmount),
                                    InsuranceAmount = tg.Sum(e => e.InsuranceAmount),
                                    SelfPayAmount = tg.Sum(e => e.SelfPayAmount),
                                    ItemCount = tg.Count()
                                })
                                .OrderByDescending(tg => tg.TotalAmount)
                                .ToList()
                        })
                        .OrderByDescending(g => g.Date)
                        .ToList();

                    statistics.DailyStatistics = groupByDay;
                }

                result.Code = APIEnums.Success;
                result.Msg = "获取费用统计成功";
                result.Data = statistics;

                logger.LogInformation($"获取住院费用统计成功，病人：{statistics.PatientName}，总金额：{statistics.TotalAmount}");
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "获取住院费用统计时发生异常");
                result.Code = APIEnums.Error;
                result.Msg = "获取费用统计时发生异常：" + ex.Message;
            }

            return Task.FromResult(result);
        }
    }
} 